﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WiiGeeDotNET;
using WiiGeeDotNet.events;
using System.Threading;
using WiimoteLib;
using System.IO;
using WiiGeeDotNet.logic;

namespace WiiGeeTest
{
  public partial class MainForm : Form
  {
    #region Fields
    private System.Windows.Forms.Timer idleTimer;
    private WiiGeeHandler m_wiigee;
    private float m_currentValue = 0;
    #endregion

    public MainForm()
    {
      InitializeComponent();
      m_wiigee = WiiGeeHandler.GetInstance();
      m_wiigee.NewGesture += m_wiigee_NewGesture;
    }

    void m_wiigee_NewGesture(GestureEvent _event)
    {
      Invoke(new Action<GestureEvent>(delegate(GestureEvent ev)
      {
        if (m_wiimote != null)
        {
          m_wiimote.SetRumble(true);
          Thread.Sleep(200);
          m_wiimote.SetRumble(false);
        }
        if (ev.Id != -99)
        {
          lblGestureName.Text = ev.Name;
          pbPropability.Value = (int)(ev.Probability * 100);
        }
        else
        {
          lblGestureName.Text = "Unknown Gesture";
          pbPropability.Value = 0;
        }
      }), _event);

    }


    private void MainForm_Load(object sender, EventArgs e)
    {

    }







    private bool m_running = false;
    private bool m_APressed;
    private bool m_BPressed;
    private bool m_HomePressed;


    void wiimote_Updated(object sender, EventArgs e)
    {
      //Accelerometer a = m_selectedWiimote.Accelerometer;
      //m_wiigee.AddAccelerationValue((double)a.Calibrated.X, (double)a.Calibrated.Y, (double)a.Calibrated.Z);
    }

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {

      if (m_wiimote != null)
      {
        m_wiimote.Disconnect();
      }
    }

    #region use WiimoteLib cause we're using an unsupported bt stack
    Wiimote m_wiimote;
    private void cmdConnectDirectly_Click(object sender, EventArgs e)
    {
      m_wiimote = new Wiimote();
      m_wiimote.Connect();
      m_wiimote.SetReportType(WiimoteLib.InputReport.ButtonsAccel, true);
      m_wiimote.SetLEDs(true, false, false, true);
      accBar.AutoRefresh = true;
      accBar.AutoRefreshRateMs = 30;
      m_wiimote.WiimoteChanged += new EventHandler<WiimoteChangedEventArgs>(m_wiimote_WiimoteChanged);
    }

    void m_wiimote_WiimoteChanged(object sender, WiimoteChangedEventArgs e)
    {
      AccelState a = m_wiimote.WiimoteState.AccelState;
      m_wiigee.AddAccelerationValue((double)a.Values.X, (double)a.Values.Y, (double)a.Values.Z);
      accBar.AddValue(a.Values.X, a.Values.Y, a.Values.Z);
      if (a.RawValues.Y < 117 || a.RawValues.Y > 119)
      {
        m_currentValue += a.RawValues.Y -118;
      }
      txtX.Text = m_currentValue.ToString();// a.RawValues.Y.ToString();

      if (m_wiimote.WiimoteState.ButtonState.A)
      {
        if (!m_APressed)
        {
          m_APressed = true;
          m_wiigee.BeginTrainGesture();
          Console.WriteLine("A pressed, start gesture training");
        }
      }
      else if(m_APressed)
      {
        m_APressed = false;
        m_currentValue = 0;
        m_wiigee.EndTrainGesture();
        Console.WriteLine("A released, stop gesture training");
      }

      if (m_wiimote.WiimoteState.ButtonState.B)
      {
        if (!m_BPressed)
        {
          m_BPressed = true;
          m_wiigee.BeginAnalyzing();
          Console.WriteLine("B pressed, start gesture recognition");
        }
      }
      else if(m_BPressed)
      {
        m_BPressed = false;
        m_wiigee.EndAnalyzing();
        Console.WriteLine("B released, stop gesture recognition");
      }

      if (m_wiimote.WiimoteState.ButtonState.Home)
      {
        if (!m_HomePressed)
        {
          m_HomePressed = true;
          GestureCreator form = new GestureCreator();

          if (form.ShowDialog() == DialogResult.OK)
          {
            String name = form.GestureName;
            int id = m_wiigee.CommitGesture(name);
            
            Console.WriteLine("Apply trained gesture (" + id + ", " + name + ")");
          }
          else
          {
            Console.WriteLine("Discarding gesture");
            m_wiigee.DiscardTrainingData();
          }
        }
      }
      else if(m_HomePressed)
      {
        m_HomePressed = false;
      }
    }

    #endregion

    private void gesturesToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
    {
      gesturesToolStripMenuItem.DropDownItems.Clear();
      foreach (GestureModel g in m_wiigee.GestureModels.Values)
      {
        ToolStripMenuItem item = new ToolStripMenuItem(g.Name);
        item.Tag = g;
        item.Click += new EventHandler(item_Click);
        gesturesToolStripMenuItem.DropDownItems.Add(item);
      }
    }

    void item_Click(object sender, EventArgs e)
    {
      GestureModel data = (GestureModel)((ToolStripMenuItem)sender).Tag;
      GestureModel newGest = new GestureModel(data.Id, data.GetGestureData());
      File.WriteAllText(Application.StartupPath + "\\" + data.Name + ".xml", data.GetGestureData());
    }

    private void loadGesturesToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
    {
      loadGesturesToolStripMenuItem.DropDownItems.Clear();
      string[] files = Directory.GetFiles(Application.StartupPath, "*.xml");
      foreach (String f in files)
      {
        ToolStripMenuItem loadItem = new ToolStripMenuItem(f);
        loadItem.Tag = f;
        loadItem.Click += new EventHandler(loadItem_Click);
        loadGesturesToolStripMenuItem.DropDownItems.Add(loadItem);
      }
    }

    void loadItem_Click(object sender, EventArgs e)
    {
      String file = (String)((ToolStripMenuItem)sender).Tag;
      m_wiigee.AddGesture(File.ReadAllText(file));
      //sender
    }

    private void gesturesToolStripMenuItem_Click(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {
      DateTime a = DateTime.Now;
      for (int i = 0; i < 2500; i++)
      {
        byte[] moviehash = ComputeMovieHash(@"F:\Upload\Smallville.S08E14.HDTV.XviD-NoTV.avi");
        Console.WriteLine("The hash of the movie-file is: {0}", ToHexadecimal(moviehash));
      }
      txtX.Text = (DateTime.Now - a).TotalMilliseconds.ToString();
    }

    private byte[] ComputeMovieHash(string filename)
    {
      byte[] result;
      using (Stream input = File.OpenRead(filename))
      {
        result = ComputeMovieHash(input);
      }
      return result;
    }

    private byte[] ComputeMovieHash(Stream input)
    {
      long lhash, streamsize;
      streamsize = input.Length;
      lhash = streamsize;

      long i = 0;
      byte[] buffer = new byte[sizeof(long)];
      while (i < 65536 / sizeof(long) && (input.Read(buffer, 0, sizeof(long)) > 0))
      {
        i++;
        lhash += BitConverter.ToInt64(buffer, 0);
      }

      input.Position = Math.Max(0, streamsize - 65536);
      i = 0;
      while (i < 65536 / sizeof(long) && (input.Read(buffer, 0, sizeof(long)) > 0))
      {
        i++;
        lhash += BitConverter.ToInt64(buffer, 0);
      }
      input.Close();
      byte[] result = BitConverter.GetBytes(lhash);
      Array.Reverse(result);
      return result;
    }

    private static string ToHexadecimal(byte[] bytes)
    {
      StringBuilder hexBuilder = new StringBuilder();
      for (int i = 0; i < bytes.Length; i++)
      {
        hexBuilder.Append(bytes[i].ToString("x2"));
      }
      return hexBuilder.ToString();
    }
  }
}
